/******************************************************************************
 * (C) 671643387@qq.com
 */

#include "ThreadPool.h"
#include <cassert>
#include <memory>
#include <Poco/Mutex.h>
#include <Poco/ScopedLock.h>
#include "Session.h"
#include "Thread.h"

namespace Shared {
    namespace Net {

        /**
         * 默认线程池
         */
        static ThreadPool* DEFAULT_POOL = nullptr;
        static Poco::FastMutex DEFAULT_POOL_LOCK;
        static void __createDefaultPool() {
            Poco::ScopedLock<Poco::FastMutex> lock(DEFAULT_POOL_LOCK);
            if (!DEFAULT_POOL) {
                DEFAULT_POOL = new ThreadPool();
                assert(DEFAULT_POOL);
            }
        }


        ThreadPool::ThreadPool()
            : _curThreads(0)
            , _threads() {

        }

        ThreadPool::~ThreadPool() {
            // 释放线程
            _curThreads = 0;
            while (_threads.size() > 0) {
                std::auto_ptr<Thread> delPtr(_threads.back());
                _threads.pop_back();
            }
        }

        void ThreadPool::setCurTherad(int nThread) {
            assert(_curThreads == 0);

            while (_curThreads < nThread) {
                _curThreads += 1;

                Thread* thread = new Thread();
                thread->start();
                _threads.push_back(thread);
            }
        }

        void ThreadPool::addSession(Session *session) {
            Thread* freeThread = findMostFreeThread();
            session->bindThread(freeThread);
        }

        void ThreadPool::stop() {
            for (std::list<Thread*>::iterator iter = _threads.begin();
                 iter != _threads.end(); ++iter) {
                (*iter)->stop();
            }
        }

        void ThreadPool::join() {
            for (std::list<Thread*>::iterator iter = _threads.begin();
                 iter != _threads.end(); ++iter) {
                (*iter)->join();
            }
        }

        ThreadPool* ThreadPool::defaultPool() {
            if (!DEFAULT_POOL) {
                __createDefaultPool();
            }
            return DEFAULT_POOL;
        }

        Thread* ThreadPool::findMostFreeThread() {
            int minLoad = INT_MAX;
            std::list<Thread*>::const_iterator find = _threads.begin();

            for (std::list<Thread*>::const_iterator iter = _threads.begin();
                    iter != _threads.end(); ++iter) {
                int curLoad = (*iter)->getLoad();
                if (curLoad < minLoad) {
                    minLoad = curLoad;
                    find = iter;
                }
            }

            return (*find);
        }
    }
}